import ij.ImagePlus;
import ij.plugin.PlugIn;
import ij.process.ColorProcessor;
import ij.process.ImageProcessor;


import java.awt.Color;


import java.awt.Font;

import java.awt.Polygon;
import java.io.PrintStream;

import java.util.ArrayList;
import java.util.Locale;
import java.util.Random; 

import pluginUtils.Point2D;
import pluginUtils.Pos3D;
import pluginUtils.Vector2D;




public class GeometricDrawer3D extends ImagePlus implements PlugIn{
	{Locale.setDefault(Locale.US); }
	
	private ImageProcessor primeIP; 
	private int X=2000,Y=2000; // image size
	
	
	private double xShift=0; 
	private double zShift=0; 
	private PrintStream outx; 
	

	private Random generator=new Random(); // One always needs some randomness
	
	// For the scaling of the image
	private double x0=0,x1=1,y0=0,y1=1;
	private double acoef,ccoef,vcoef,wcoef; 
	
	private static boolean voisin(int i,int j){
		int diff=0; 
		while(i+j!=0){
			if(i%2!=j%2) diff++;
			i=i/2;
			j=j/2; 
		}
		return diff==1; 
		
	}
	
	private String[] palette={"Yellow","Red","Blue","Green","White","NavyBlue","Turquoise","Orange"};
	private Color[] palette1={Color.YELLOW,Color.RED,Color.BLUE,Color.GREEN,Color.MAGENTA,Color.ORANGE};
	public void setCoefs(){
		acoef=X/(x1-x0); 
		vcoef=Y/(y1-y0); 
		ccoef=-acoef*x0; 
		wcoef=-vcoef*y0; 
	}
	 
	
	
	public void setBounds(double xl,double xu,double yl,double yu){
		x0=xl; 
		x1=xu;
		y0=yl;
		y1=yu; 
	}
	
	
	private void drawPoint(Point2D c){
		double xCenter=c.getX(); 
		double yCenter=c.getY(); 
		int intX=(int)(xCenter*acoef+ccoef);
		int intY=(int)(yCenter*vcoef+wcoef);
		primeIP.fillOval(intX-10,intY-10,20,20);
	}
	
	
	
	
	
	private void drawLine(double xd,double yd,double xf,double yf){
		int XD=(int)(xd*acoef+ccoef); 
		int YD=(int)(yd*vcoef+wcoef); 
		int XF=(int)(xf*acoef+ccoef); 
		int YF=(int)(yf*vcoef+wcoef);
		primeIP.drawLine(XD,YD,XF,YF); 
	}
	
	private void drawLine(Vector2D x1,Vector2D x2){
		int XD=(int)(x1.getX()*acoef+ccoef); 
		int YD=(int)(x1.getY()*vcoef+wcoef); 
		int XF=(int)(x2.getX()*acoef+ccoef); 
		int YF=(int)(x2.getY()*vcoef+wcoef);
		primeIP.drawLine(XD,YD,XF,YF); 
	}
		
	
	
	
	
	public void run(String arg) {
		primeIP = new ColorProcessor(X,Y);
		
		
		double limit=4; 
		
		setBounds(-limit,limit,-limit,limit); 
		setCoefs(); 
		
		
		
		
		
		
		Polygon background=new Polygon(new int[]{0,0,X,Y},new int[]{0,X,Y,0},4);
		primeIP.setColor(Color.WHITE);
		
		primeIP.fillPolygon(background);
		
		
		primeIP.setFont(new Font(null,Font.ITALIC,60));
		primeIP.setColor(Color.BLACK);
		primeIP.setLineWidth(3); 
	
		setProcessor("Verifying", primeIP);
		
		//drawLine(x0,0,x1,0);
		//drawLine(0,y0,0,y1);
		
		int dim=9;
		double phi=1.61828;
		double iph=1/phi;
		
		int taille=512;
		Pos3D vectorSet[]=new Pos3D[dim];
		
		vectorSet[0]=new Pos3D(0,iph,phi);
		vectorSet[1]=new Pos3D(0,iph,-phi);
		vectorSet[2]=new Pos3D(phi,0,iph);
		vectorSet[3]=new Pos3D(phi,0,-iph);
		vectorSet[4]=new Pos3D(iph,phi,0);
		vectorSet[5]=new Pos3D(iph,-phi,0);
		vectorSet[6]=new Pos3D(1,1,1);
		vectorSet[7]=new Pos3D(1,1,-1);
		vectorSet[8]=new Pos3D(1,-1,1);
		//vectorSet[9]=new Pos3D(-1,1,1);
		
		
		
		Pos3D allPoints[]=new Pos3D[taille];
		
		try{
			
			outx=new PrintStream("/tmp/outzono3d.txt");
			double coef[]={-1,1}; 
			
			
		for(int i=0;i<taille;i++){
			int n=i; 
			Pos3D sum=new Pos3D(0,0,0);
			
			for(int k=0;k<dim;k++){
				sum=Pos3D.add(sum, Pos3D.mul(vectorSet[k],coef[n%2])); 
				n=n/2; 
			}
			allPoints[i]=sum; 
			//drawPoint(sum); 
		}
	
		double torse=Math.PI/3;
		double xmax=0; 
		double ymax=0;
		double zmax=0;
		int k=0; 
		for(int i=0;i<taille;i++){
			double xi=allPoints[i].getX();
			double yi=allPoints[i].getY(); 
			double zi=allPoints[i].getZ();
			if(xi>xmax)xmax=xi;
			if(yi>ymax)ymax=yi;
			if(zi>zmax)zmax=zi;
			
			if(xi+yi+zi!=0){
			String p="sphere{<"+xi+","+yi+","+zi+">,diam  texture{Texture0} finish{Finish0}}";
			outx.println(p);
			}
			for(int j=i+1;j<taille;j++)
				if(voisin(i,j)) {
					//drawLine(allPoints[i],allPoints[j]);
					
					double xj=allPoints[j].getX(); 
					double yj=allPoints[j].getY();
					double zj=allPoints[j].getZ();
					if((xi==0)&&(yi==0)&&(zi==0)) break;
					if((xj==0)&&(yj==0)&&(zj==0)) break;
					
					drawLine(new Vector2D(xi,yi),new Vector2D(xj,yj));
					
					String c="cylinder{<"+xi+","+yi+","+zi+">,<"+xj+","+yj+","+zj+">,diam "; 
					System.out.println(c); 
					c+="texture{Texture0} finish{Finish0}}";
					
					k++; 
					if(k%1000==0)
					System.out.println(k);
					outx.println(c);
				}
		}
		System.out.println("-->"+xmax+" "+ymax+" "+zmax);
		}
		catch(Exception e){System.out.println(e);}
		show();
		
		}
	}	

	